package com.weme.common.ext

import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import com.google.protobuf.ByteString
import com.google.protobuf.MessageLite
import com.osom.proto.message.NetworkOuterClass
import com.weme.common.buff.IoBuffer
import com.weme.common.manager.SocketConnectManager
import com.weme.common.socket.*
import com.weme.common.util.UserMKHelper
import com.weme.common.util.DeviceUtils
import java.nio.ByteBuffer
import java.nio.ByteOrder

/**
 * 网络的工具类
 *
 * @author
 */


/**
 * 写一个简单LiveData的Filter扩展方法便于使用
 */
fun <T> LiveData<T>.filter(test: (T) -> Boolean): LiveData<T> {
    val result = MediatorLiveData<T>()
    result.addSource(this) {
        if (test(it)) {
            result.value = it
        }
    }
    return result
}




/**
 * 一个简单的NetworkOuterClass.Network类型创建的扩展方法
 *
 * @param payload 传递数据包 可以为null,无默认值
 * @param cmdId 发送的命令id，可以根据payload数据类型自己判断但是要扩展getCmdIdByPayload方法
 * @param uid 用户的uid，有默认值，一般不需要修改
 * @param ukey socket登陆成功返回的，有默认值，一般不需要修改
 * @param version 有默认值，一般不需要修改
 * @param subversion 有默认值，一般不需要修改
 * @param srcSv 有默认值，一般不需要修改
 * @param destSv 有默认值，一般不需要修改
 *
 * @author
 */
fun NetworkOuterClass.Network.Builder.create(
    payload: MessageLite?,
    cmdId: Int = 32,
    uid: Long = UserMKHelper.decodeLong(UserMKHelper.UID),
    ukey: Long = SocketConnectManager.getUKey(),
    version: Int = DeviceUtils.getAppVersionCode(),
    subversion: Long ,
    seq: Long = 0,
): NetworkOuterClass.Network {
    val network = setCmdid(cmdId)
        .setUid(UserMKHelper.decodeLong(UserMKHelper.UID))
        .setCmdid(cmdId)
        .setUkey(ukey)
        .setVersion(version)
        .setSubversion(subversion)
        .setMessageseq(seq.toLong())

        .also {
            if (payload != null) {
                it.payload = ByteString.copyFrom(payload.toByteArray())
            }
        }
        .build()
    return network
}

fun NetworkOuterClass.Network.Builder.create(
    payload: ByteBuffer?,
    cmdId: Int = 32,
    uid: Long = UserMKHelper.decodeLong(UserMKHelper.UID),
    ukey: Long = SocketConnectManager.getUKey(),
    version: Int = DeviceUtils.getAppVersionCode(),
    subversion: Long ,
    seq: Long = 0,
): NetworkOuterClass.Network {
    val network = setCmdid(cmdId)
        .setUid(UserMKHelper.decodeLong(UserMKHelper.UID))
        .setUkey(ukey)
        .setVersion(version)
        .setSubversion(subversion)
        .setMessageseq(seq)

        .also {
            if (payload != null) {
                it.payload = ByteString.copyFrom(payload)
            }
        }
        .build()
    return network
}


/**
 * 将发送的发送数据转化成小端数据，和服务约定的必须转成小段数据，为了方便使用所以写了这个扩展
 *
 * @author
 */
fun MessageLite.toLittleEndianSizeBuff(): ByteBuffer {
    val orgByteArray = toByteArray()
    val messageSize = orgByteArray.size

    // 分配足够的空间来容纳消息大小和消息数据
    val destByteBuff = ByteBuffer.allocate(4 + messageSize).order(ByteOrder.LITTLE_ENDIAN)

    // 写入消息的总长度
    destByteBuff.putInt(messageSize)

    // 写入消息数据
    destByteBuff.put(orgByteArray)

    // 切换到读模式
    destByteBuff.flip()
    return destByteBuff
}